#pragma once
#include<iostream>
#include<thread>
#include<mutex>
#include<functional>
using namespace std;
namespace cfy
{
	template<class T>
	class auto_ptr
	{
	public:
		//保存资源
		auto_ptr(T* ptr)
			:_ptr(ptr)
		{}
		//释放资源
		~auto_ptr()
		{
			delete[] _ptr;
			cout << _ptr << endl;
		}

		auto_ptr(auto_ptr<T>& sp)
			:_ptr(sp._ptr)
		{
			sp._ptr = nullptr;
		}

		//像指针一样
		T& operator*()
		{
			return *_ptr;
		}

		T& operator[](size_t pos)
		{
			return _ptr[pos];
		}
	private:
		T* _ptr;
	};

	template<class T>
	class unique_ptr
	{
	public:
		//RAII
		unique_ptr(T* ptr = nullptr)
			:_ptr(ptr)
		{}
		~unique_ptr()
		{
			if (_ptr != nullptr)
			{
				cout << "delete: " << _ptr << endl;
				delete _ptr;
				_ptr = nullptr;
			}
		}
		//可以像指针一样使用
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		//防拷贝
		unique_ptr(unique_ptr<T>& up) = delete;
		unique_ptr& operator=(unique_ptr<T>& up) = delete;
	private:
		T* _ptr;//管理的资源
	};


	//template<class T>
	//class shared_ptr
	//{
	//private:
	//	//++引用计数
	//	void AddRef()
	//	{
	//		_pmutex->lock();
	//		(*_pcount)++;
	//		_pmutex->unlock();
	//	}
	//	//--引用计数
	//	void ReleaseRef()
	//	{
	//		_pmutex->lock();
	//		bool flag = false;
	//		if (--(*_pcount) == 0)
	//		{
	//			if (_ptr != nullptr)
	//			{
	//				cout << "delete: " << _ptr << endl;
	//				delete _ptr;
	//				_ptr = nullptr;
	//			}
	//			delete _pcount;
	//			_pcount = nullptr;
	//			flag = true;
	//		}
	//		_pmutex->unlock();
	//		if (flag == true)
	//		{
	//			delete _pmutex;
	//		}

	//	}
	//public:
	//	//RAII
	//	shared_ptr(T* ptr = nullptr)
	//		:_ptr(ptr)
	//		, _pcount(new int(1))
	//	{}
	//	~shared_ptr()
	//	{
	//		ReleaseRef();
	//	}

	//	shared_ptr(shared_ptr<T>& sp)
	//		:_ptr(sp._ptr)
	//		, _pcount(sp._pcount)
	//	{
	//		AddRef();
	//	}

	//	shared_ptr& operator=(shared_ptr<T>& sp)
	//	{
	//		if (_ptr != sp._ptr)//管理同一块空间的对象之间无需进行赋值操作
	//		{
	//			ReleaseRef();
	//			_ptr = sp._ptr;       //与sp对象一同管理它的资源
	//			_pcount = sp._pcount; //获取sp对象管理的资源对应的引用计数
	//			AddRef();       //新增一个对象来管理该资源，引用计数++
	//		}
	//		return *this;
	//	}

	//	//获取引用计数
	//	int use_count()
	//	{
	//		return *_pcount;
	//	}
	//	//可以像指针一样使用
	//	T& operator*()
	//	{
	//		return *_ptr;
	//	}
	//	T* operator->()
	//	{
	//		return _ptr;
	//	}

	//private:
	//	T* _ptr;	 //管理的资源
	//	int* _pcount;//管理的资源对应的引用计数
	//	mutex* _pmutex;//管理的资源对应的互斥锁
	//};

	//默认的删除器
	template<class T>
	struct Delete
	{
		void operator()(const T* ptr)
		{
			delete ptr;
		}
	};
	template<class T, class D = Delete<T>>
	class shared_ptr
	{
	private:
		void ReleaseRef()
		{
			_pmutex->lock();
			bool flag = false;
			if (--(*_pcount) == 0) //将管理的资源对应的引用计数--
			{
				if (_ptr != nullptr)
				{
					cout << "delete: " << _ptr << endl;
					_del(_ptr); //使用定制删除器释放资源
					_ptr = nullptr;
				}
				delete _pcount;
				_pcount = nullptr;
				flag = true;
			}
			_pmutex->unlock();
			if (flag == true)
			{
				delete _pmutex;
			}
		}
		//...
	public:
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _pmutex(new mutex)
			, _del(del)
		{}
		//...
	private:
		T* _ptr;        //管理的资源
		int* _pcount;   //管理的资源对应的引用计数
		mutex* _pmutex; //管理的资源对应的互斥锁
		D _del;         //管理的资源对应的删除器
	};


	template<class T>
	class weak_ptr
	{
	public:
		weak_ptr()
			:_ptr(nullptr)
		{}
		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get())
		{}
		weak_ptr& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();
			return *this;
		}
		//可以像指针一样使用
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr; //管理的资源
	};
}

